perm filename CURVES.MF[MF,DEK] blob
sn#751800 filedate 1984-04-27 generic text, type T, neo UTF8
% this file was used in the lecture about curves
delimiters (); % ( and ) are like parens
def down=(0,-1) enddef; % define four basic directions
def up=(0,1) enddef;
def right=(1,0) enddef;
def left=(-1,0) enddef;
def angle primary d = (cosd d, sind d) enddef; % and an arbitrary one
vardef z@#=(x@#,y@#) enddef; % continue basic setup as in demo.mf
edges e;
e=nulledges;
def draw expr x = addto e contour x withweight 1 enddef;
def erase expr x = addto e contour x withweight -1 enddef;
openwindow 1 from (0,0) to (400,450) at (-100,200);
smoothing:=1; autorounding:=2;
hppp:=300/72.27; vppp:=hppp;
charcode:=96;
def next = % this macro finishes one character and starts another:
display e on 1; % show what you've got
shipout e; % output it
e:=nulledges; % reset to blank
charcode:=charcode+1; % advance to the next character number
enddef;
tracingonline:=1; pausing:=1;
h=v=4; % now we'll define the same points as last time, magnified fourfold
z1=(6h,0); z2=(0,8v); z3=(4h,11v); z4=(10h,8v); z5=(17h,9v); z6=(18h,2v);
z0=(9h,3v);
for n:=1 step 1 until 6: z[n]a-z0 = 2(z[n]-z0); endfor
% specifying directions at some of the points
% (last time METAFONT chose all directions by itself)
draw z1a{left}..z2a{up}..z3a..z4a..z5a..z6a..cycle;
erase z1{left}..z2{up}..z3..z4..z5..z6..cycle;
next;
% same, but with weirder directions
draw z1a{up}..z2a{left}..z3a..z4a..z5a..z6a..cycle;
erase z1{up}..z2{left}..z3..z4..z5..z6..cycle;
next;
show up,left; % this shows that up=(0,1) and left=(-1,0)
% [any direction is possible]
% here we force the curve to be a straight line between points 1 and 2
draw z1a{z2a-z1a}..z2a{z2a-z1a}..z3a..z4a..z5a..z6a..cycle;
erase z1{z2-z1}..z2{z2-z1}..z3..z4..z5..z6..cycle;
next;
% An `&' joins two independent pieces that touch
draw z1a..z2a..z3a..z4a & z4a..z5a..z6a..cycle;
erase z1..z2..z3..z4 & z4..z5..z6..cycle;
next;
% two other ways to get the same thing:
draw z1a..z2a..z3a..z4a..z4a..z5a..z6a..cycle; % repeat a point twice
erase z1..z2..z3..z4{curl 1}..z5..z6..cycle; % specify a "curl"
next;
% you can ask for more or less curl
draw z1a..z2a..z3a..z4a{curl 2}..z5a..z6a..cycle;
erase z1..z2..z3..z4{curl 0}& z4..z5..z6..cycle;
% that was "curl 0" at the left, "curl 1" (the default) at the right
next;
% here we put the curl at points 3 and 5 instead
draw z1a..z2a..z3a{curl 1}..z4a..z5a{curl 1}..z6a..cycle;
path p; p=z3..z4..z5;
erase z1..z2..z3 & p & z5..z6..cycle;
next;
% here we connect neighboring points by straight lines
erase z1..z2&z2..z3&z3..z4&z4..z5&z5..z6&z6..z1&cycle;
draw z1a..z2a&z2a..z3a&z3a..z4a&z4a..z5a&z5a..z6a&z6a..z1a&cycle;
next;
% notice that it's possible to erase before drawing!
% now here's a tricky way to change the meaning of ".."
% by calling it a "text parameter" to a macro:
def demochar(text ..)=
draw z1a..z2a..z3a..z4a..z5a..z6a..cycle;
erase z1..z2..z3..z4..z5..z6..cycle;
next;
enddef;
% you can vary the "tension" of the curve between points
demochar(..);
% that's the default
% (same as tension 1)
demochar(..tension 2..);
% now pull tighter
demochar(..tension 1.2..);
% now pull only a bit tighter
demochar(..tension 1000..);
% now pull really hard
demochar(..tension 3/4..);
% now push a bit
% (3/4 is the minimum allowed)
demochar(..tension 1 and 2..);
% tension is 1 when leaving a point
% and 2 when coming into the next
demochar(..tension 2 and 1..);
% here it's the other way 'round
path a.in, a.out; % declare two variables of type "path"
a.out = % data taken from bitpad for a Baskerville "a"
(30.8154h,30.5538v)..(24.1231h,25.7692v)..(15.1231h,23.3692v)..(07.1692h,26.1692v)
..(03.6308h,33.6154v)..(10.0154h,44.2000v)..((23.0462h,51.3385v)..(27.2308h,53.2000v))
..(29.6615h,54.8000v)..((30.2000h,56.8923v)..(30.2154h,62.7846v))
..(29.7538h,66.2308v)..(27.5385h,69.8308v)..(21.7692h,71.4923v)..(17.2462h,70.8769v)
..(13.3538h,68.0462v)..((12.7538h,65.4000v)..(12.6462h,64.1692v))
..(11.3385h,61.2154v)..(09.3385h,60.5077v)..(06.9231h,61.4769v)..(05.6000h,64.2615v)
..(07.0154h,68.6923v)..(11.1538h,71.8923v)..(21.8000h,73.7846v)..(30.8154h,72.6000v)
..(38.0154h,67.7538v)..((39.2615h,60.7538v)..(39.4154h,36.1692v))
..(39.7231h,31.5538v)..(41.3231h,28.9077v)..(43.6462h,28.1231v)..(46.9385h,29.7385v)
..(48.1538h,32.2000v)
&(48.1538h,32.2000v)..(49.8462h,32.1077v)
&(49.8462h,32.1077v)..(47.4923h,26.3538v)..(41.2000h,23.5231v)..(35.0615h,25.4923v)
..(30.8154h,30.5538v) & cycle;
a.in =
((30.2154h,51.7692v)..(30.4308h,34.5385v))
..((28.0000h,31.0154v){curl 0}..(20.4769h,28.1385v)..(14.7077h,30.9077v)
..(13.2462h,36.2000v)..(17.1846h,44.3077v)..(30.2154h,51.7692v){curl 0}) & cycle;
draw a.out; erase a.in;
next;
% METAFONT actually computes two "control points" between every
% pair of given points on the curve.
tracingchoices:=1; % you can see them by asking for this
% here's a path that leaves (0,0) at a 30 degree angle
% and comes in at a 60 degree angle:
show (0,0){angle 30}..(200,0){angle -60};
% (the incoming angle was said to be -60 because the path
% is actually traveling downward with respect to the
% horizon at the ending point)
% METAFONT shows the following in response to the above:
% Path at line 9, before choices:
% (0,0){0.86603,0.5}
% ..(200,0){0.5,-0.86601}
%
% Path at line 9, after choices:
% (0,0)..controls (73.33493,42.33983) and (163.26099,63.63289)
% ..(200,0)
% for comparison, here are two more cases:
show (0,0){angle 30}..(200,0);
% Path at line 28, before choices:
% (0,0){0.86603,0.5}
% ..(200,0){curl 1}
%
% Path at line 28, after choices:
% (0,0)..controls (61.88023,35.72647) and (138.11977,35.72647)
% ..(200,0)
show (0,0){angle 30}..(200,0){curl 2};
% Path at line 38, before choices:
% (0,0){0.86603,0.5}
% ..(200,0){curl 2}
%
% Path at line 38, after choices:
% (0,0)..controls (63.67577,36.76312) and (142.7106,43.95956)
% ..(200,0)
tracingchoices:=0; % now stop showing the choices of control points
% finally, we look at some of the ways a curve will vary
% when one of its angles is changing:
def tickmarks =
draw (-5,0)..tension100..(0,0)..tension100..
(0,-2)..tension100..(-5,-2)..tension100..cycle;
draw (205,0)..tension100..(200,0)..tension100..
(200,-2)..tension100..(205,-2)..tension100..cycle;
enddef;
def finish = % make it look like a loaf of bread baking
(200,0)..(200,-100){down}..tension10..(0,-100){up}..(0,0) & cycle;
tickmarks; next;
enddef;
draw (0,0){angle 30}..(200,0){angle -60} & finish;
draw (0,0){angle 60}..(200,0){angle -60} & finish;
draw (0,0){angle120}..(200,0){angle -60} & finish;
draw (0,0){angle-30}..(200,0){angle -60} & finish;
erase (0,0){angle 30}..(200,0){angle -60} &
(200,0)..(200,-100){down}..tension10..(0,-100){up}..(0,0) & cycle;
draw (0,0){angle 60}..(200,0){angle -60} & finish;
end